home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 406_01 / disked25 / source / disked.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  40.4 KB  |  1,424 lines

  1. /***
  2. *disked.c - disk editor
  3. *
  4. *Copyright (c) 1991-1994, Gregg Jennings.  All wrongs reserved.
  5. *   P O Box 200, Falmouth, MA 02541-0200
  6. *
  7. *Purpose:
  8. *   MS(tm)-DOS Disk EDitor
  9. *
  10. *Notice:
  11. *   This progam may be freely used and distributed.  Any distrubution
  12. *   with modifications must retain the above copyright statement and
  13. *   modifications noted.
  14. *   No pulp-publication, in whole or in part, permitted without
  15. *   permission (magazines or books).
  16. *******************************************************************************/
  17.  
  18. /*
  19.    Versions:
  20.  
  21.    2.1 04-Jan-1994   added Translate if !Files for startup, Borland
  22.                      added 'dir_cluster'
  23.    2.0 28-Nov-1993
  24.  
  25.    Release Notes:
  26.  
  27.    Programming Notes:
  28.  
  29.    The use of specialized printing functions (conout(), send(), putint()
  30.    et cetera) is because printf() is MUCH to slow on XT's.  The screen
  31.    output is significantly faster.
  32. */
  33.  
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <conio.h>
  37. #include <ctype.h>
  38. #include <stdlib.h>
  39. #include <malloc.h>
  40. #include <dos.h>
  41. #include <fcntl.h>
  42. #include <io.h>
  43. #include <direct.h>
  44. #include <process.h>
  45. #include <errno.h>
  46.  
  47. #include "disked.h"
  48. #include "mylib.h"
  49. #include "diskio.h"
  50. #include "keys.h"
  51. #include "files.h"
  52. #include "alloc.h"
  53. #include "error.h"
  54. #include "dirent.h"
  55. #include "direct.h"
  56.  
  57. extern char findstr[];     /* for find() */
  58.  
  59. struct Msg ps[]={          /* for inputing a two argument commnd */
  60.    " from ",6,
  61.    " number ",3,
  62. };
  63.  
  64. struct Msg ap[]={          /* for inputing a two argument commnd */
  65.    " from ",3,
  66.    " number ",3
  67. };
  68.  
  69. struct Msg st[]={          /* three argument command 's' */
  70.    " track ",3,
  71.    " sector ",2,
  72.    " head ",1
  73. };
  74.  
  75. struct Keys kw[]={
  76.    0,15,"",                      /* 15 is number of entries -1 */
  77.    ALTD,1, "display",
  78.    ALTG,0, "get",
  79.    ALTH,1, "home",
  80.    ALTM,1, "mask",               /* kw[4].s */
  81.    ALTV,1, "verify",
  82.    ALTW,0, "write",
  83.    ALTS,1, "strip",              /* kw[7].s */
  84.    ALTC,1, "convert",            /* kw[8].s */
  85.    ALTF,0, "files",
  86.    0,   0, "Debug",
  87.    ALTA,0, "ascii",
  88.    ALTP,1, "partial",
  89.    ALTL,1, "logical",
  90.    ALTT,0, "translate",
  91.    ALTR,10,"radix",              /* leave this one last */
  92. };
  93.  
  94. #ifndef __BORLANDC__
  95. #define FILENAME_MAX 63
  96. #endif
  97. char comspec[FILENAME_MAX];
  98. char inifile[FILENAME_MAX];
  99. char savfile[FILENAME_MAX];
  100. char curdir[FILENAME_MAX];      /* temp strings, not too big... */
  101.  
  102. int min_mem;                    /* testing purposes only, for running */
  103.                                 /* within an IDE such as MS-QuickC */
  104.  
  105. unsigned int byte_cnt;          /* buffer byte count */
  106. unsigned int max_bytes;         /* maximum buffer size */
  107. unsigned char *save_sec;        /* duplicate sector buffer */
  108. unsigned char *spare_sec;       /* spare sector buffer */
  109. unsigned char *data_buf;        /* pointer to area for data buffer */
  110. int write_to;                   /* double protection on write */
  111. unsigned long tagged[10];
  112. unsigned int dir_cluster;
  113.  
  114. int Signon;
  115. int Save,Restore;
  116. int files_indexed;
  117. int find_flag;
  118.  
  119. int _cdecl main(int argc,char **argv)
  120. {
  121. unsigned int c;
  122. char tmpstr[MAXSTR+1];
  123. char ccurdir[67];
  124. unsigned int cdisk;
  125. register unsigned int u;        /* vars for loops */
  126. register int i;
  127. unsigned int temps,tempt,temph,tempu;
  128. long templ;
  129. int tempd;
  130. unsigned int bufptr;            /* pointer to file buffer */
  131. int drives[MAX_DRIVE+1];        /* valid drive number array  1-MAX_DRIVE */
  132. int noput;
  133. int moved;
  134. char *bufferfull=" buffer full ";
  135.  
  136.    volume[0]=format[0]=fatsize[0]=tmpstr[0]='\0';
  137.    bufptr = moved = 0;
  138.    noput = TRUE;
  139.  
  140.    dir_cluster = 0;
  141.  
  142. #ifndef NDEBUG
  143.    printf("");    /* for alloc/free debugging; MSC will call malloc */
  144.                   /* during first printf() */
  145. #endif
  146.    error.num = -1;
  147.  
  148.    cdisk = setup(argv,drives,&disk);
  149.  
  150.    if (Restore)
  151.    {
  152.       if (Display && !Verify)
  153.          print("restoring...");
  154.       if (Verify && getver(" restore",0))
  155.          getinit(savfile);
  156.       else
  157.          Restore=FALSE;
  158.    }
  159.    u = (min_mem) ? 8192U : 65024U;
  160.  
  161.    /* try and get memory */
  162.  
  163.    for (;;u-=512U)
  164.       if ((data_buf=(unsigned char *)alloc(u,sizeof(char)))!=NULL)
  165.          break;
  166.    if (u < 512U*10U)
  167.       quit(NO_MEM);
  168.    max_bytes = u;
  169.  
  170.    getcwd(ccurdir,66);                       /* save current directory */
  171.    memset(tagged,0,sizeof(tagged));
  172.  
  173.    while ((i=logdisk(disk)) != DISK_OK)      /* log disk in */
  174.    {
  175.       printerror(Debug);
  176.       if (disk==cdisk)
  177.          exit(2);
  178.       conout(' ');
  179.       conout(disk+'@');
  180.       conout(':');
  181.       print(" Use current? (or Retry) ");    /* get another ? */
  182.       if ((c=input())=='y' || c=='Y')
  183.          disk=cdisk;                         /* use current drive */
  184.       else if (c!='r' && c!='R')
  185.          exit(0);
  186.       send('\n');
  187.    }
  188.  
  189.    /****** can only alloc sector buffer if sector size is known ******/
  190.  
  191.    if ((sec_buf=alloc(sec_size,sizeof(char)))==NULL)
  192.       quit(NO_MEM);
  193.  
  194.    if ((save_sec=alloc(sec_size,sizeof(char)))!=NULL)
  195.       if ((spare_sec=alloc(sec_size,sizeof(char)))==NULL)
  196.          freep(save_sec);
  197.  
  198.    if (getcwd(curdir,66) == NULL)
  199.       perror("getcwd()");
  200.  
  201.    /* all done with initialization, now check for commands via command line */
  202.  
  203.    /*
  204.       First do Special Commands which bypass normal start-up sequence
  205.       only one for now: /f{text}.  Note that the order of /f and +|-f
  206.       on the command line is followed.
  207.    */
  208.  
  209.    if (find_flag)             /* find text via command line */
  210.    {
  211.       rootsector();
  212.       if (Display)
  213.       {
  214.          printc(Title);       /* display (centered) logo */
  215.          printc(Copyr);
  216.       }
  217.       if (find_flag == 1)
  218.          i = do_files();
  219.       else
  220.          i = 1;
  221.       if (error.num != -1)
  222.       {
  223.          send('\n');
  224.          printerror(Debug);
  225.          send('\n');
  226.       }
  227.       if (i == 0 && Verify)
  228.          i = getver(" find",MOV_YN);
  229.       print("\nfind ");
  230.       print(findstr);
  231.       tempd = find(1,0,0);
  232.       if (tempd >= 0)
  233.       {
  234.          print("found at ");
  235.          pn(tempd,Radix);
  236.       }
  237.       if (find_flag == 2)
  238.          do_files();
  239.    }
  240.    /* end of Special Commands */
  241.    else
  242.    {
  243.       if (Signon == TRUE)
  244.          signon_msg();
  245.       if (Files > 0)
  246.       {
  247.          do_files();
  248.       }
  249.       else if (Signon == TRUE)
  250.       {
  251.          pause();
  252.          send('\n');
  253.       }
  254.       if (!Files)
  255.           get_volume(volume);
  256.       if (Restore)                     /* if Restored, just read current sector */
  257.          readsector();
  258.       else if (Files && !Home)         /* if indexed files and not go home */
  259.       {                                /*  set to current directory */
  260.          strcpy(tmpstr,&curdir[2]);
  261.          if ((tempd=findfile(tmpstr))!=0)
  262.             setcluster(tempd);
  263.          else
  264.             rootsector();
  265.       }
  266.       else if (cdisk == disk)
  267.       {
  268.          templ = cwdstart();
  269.          dir_cluster = sectortocluster(templ);
  270.          setsector(templ);
  271.       }
  272.       else
  273.          rootsector();
  274.  
  275.       if (!(Files && !Home && Translate)) /* display disk parameters */
  276.          dparams(curdir);                 /* if not dir display  */
  277.       print("\n\n\t'/' for help");
  278.    }
  279.  
  280.    if (error.num != -1)                   /* if error */
  281.    {
  282.       send('\n');                         /* place the message */
  283.       send('\n');                         /* in a good spot */
  284.       printerror(Debug);                  /* (before the dump) */
  285.    }
  286.    dumpsector();
  287.  
  288.    /*
  289.       The rest of the code is one huge switch/case in a loop.
  290.  
  291.       The interface I chose to use, a TTY or Teletype-like
  292.       interface (which may seem out dated to some be I find
  293.       it extremely easy to use), presents some programming
  294.       constructs that are hard to keep consistant and can
  295.       be confusing :-)
  296.    */
  297.  
  298.    for (;;)
  299.    {
  300.       if (error.num != -1)
  301.       {
  302.          if (!Verify)
  303.             conout(' ');
  304.          printerror(Debug);
  305.       }
  306.       if (moved)
  307.       {
  308.          moved = 0;
  309.          dumpsector();
  310.       }
  311.       send('\n');
  312.       c=prompt(byte_cnt,Radix);
  313.       if (c<' ')
  314.       {
  315.          conout('^');
  316.          conout(c+'@');
  317.       }
  318.       else if (c<0xff)
  319.          conout(c);
  320.  
  321.       switch(c)
  322.       {
  323.          case '!':
  324.             conout(' ');             /* if "File not found" */
  325.             if (spawnl(P_WAIT,comspec,NULL)!=-1)
  326.                moved=1;             /* display sec */
  327.             break;
  328.          case SRIGHT:               /* shift right arrow */
  329.          case SLEFT:                /* shift left arrow */
  330.             if (!Files)
  331.                break;
  332.             tempu=sectortocluster(log_sector);
  333.             if (tempu==0)
  334.                tempu=2;
  335.             temps = (c==SLEFT) ? (-1) : (1);
  336.             if (Display)
  337.             {
  338.                print( (temps==1) ? " next" : " back");
  339.                print(" free cluster");
  340.             }
  341.             for (u=tempu+temps;;u+=temps)
  342.             {
  343.                if (u>=num_clusters)
  344.                    u=2;
  345.                if (u<2)
  346.                    u=num_clusters;
  347.                if (u==tempu)
  348.                    break;
  349.                if (clusters[u] < 1)
  350.                {
  351.                    setcluster(u);
  352.                    moved=1;
  353.                    break;
  354.                }
  355.             }
  356.             break;
  357.  
  358.          case F1:
  359.             if (Files && n_files==1)
  360.                print(" no files");
  361.             else
  362.             {
  363.                print(" Current Directory: ");
  364.                print(curdir);
  365.                send('\n');
  366.                dir();
  367.             }
  368.             break;
  369.          case F2:
  370.             if (!Files)
  371.                break;
  372.             if (n_files==1)
  373.             {
  374.                print(" no files");
  375.                break;
  376.             }
  377.             for (u=1;u<n_files;u++)     /* more than 32767 files ? */
  378.             {
  379.                print("\n");
  380.                print(gfile(u));
  381.                if (kbhit())
  382.                {
  383.                   if ((c=input())==0)
  384.                      input();
  385.                   else if (c==0x1b)
  386.                      break;
  387.                   else if (c==' ')
  388.                      pause();
  389.                }
  390.            }
  391.            break;
  392.  
  393.          case SHFTF1:
  394.             dump(sec_buf,0,sec_size,128,Radix);
  395.             break;
  396.          case SHFTF2:
  397.             dumpf(sec_buf,sec_size,Radix);
  398.             break;
  399.          case SHFTF3:
  400.             view(sec_buf,0,sec_size,NOPAUSE,Radix);
  401.             break;
  402.          case SHFTF4:
  403.             dumpdir(sec_buf,sec_size);
  404.             break;
  405.          case SHFTF5:
  406.             dumpboot(sec_buf);
  407.             break;
  408.          case SHFTF6:
  409.             help();
  410.             break;
  411.          case F3:
  412.             if (!Files)
  413.                break;
  414.             conout(' ');
  415.             putuint(n_files-1);
  416.             print(" Files, ");
  417.             putuint(n_dirs);
  418.             print(" Directories");
  419.             break;
  420.          case F4:                        /* change dir */
  421.             if (Display)
  422.                print("directory ");
  423.             else
  424.                print("cd ");
  425.             if (getstr(tmpstr,MAXSTR,_PUNCT) < 1)
  426.                break;
  427.             if (chdir(tmpstr) == -1)
  428.                print(" not found");
  429.             getcwd(curdir,66);
  430.             break;
  431.          case F5:                        /* re-read */
  432.             readsector();
  433.             moved = 1;
  434.             break;
  435.          case F6: case F7:
  436.          case F8: case F9:
  437.             if (byte_cnt > (max_bytes-sec_size))
  438.                break;
  439.             if (Display)
  440.                print("append w/");
  441.             tempt = temph = temps = 0;
  442.             switch (c)
  443.             {
  444.                case F6:
  445.                    if (Display)
  446.                        print(kw[7].s);
  447.                    temph = 1;
  448.                    break;
  449.                case F7:
  450.                    if (Display)
  451.                        print(kw[8].s);
  452.                    temps = 1;
  453.                    break;
  454.                case F8:
  455.                    if (Display)
  456.                        print(kw[4].s);
  457.                    tempt = 1;
  458.                    break;
  459.                case F9:
  460.                    if (Display)
  461.                        print("options");
  462.                    tempt = Strip;
  463.                    temph = Mask;
  464.                    temps = Convert;
  465.                    break;
  466.                default:
  467.                    break;
  468.             }
  469.             append(tempt,temph,temps,sec_buf,sec_size);
  470.             break;
  471.          case F0:
  472.             if (!Files)
  473.                break;
  474.             if (n_files == 1)
  475.             {
  476.                print(" no files");
  477.                break;
  478.             }
  479.             if (Display)
  480.                print("goto ");
  481.             print("file: ");
  482.             if (getstr(tmpstr,MAXSTR,_PUNCT) < 1)
  483.                break;
  484.             if ((tempu = findfile(tmpstr)) != 0)
  485.             {
  486.                setcluster(tempu);
  487.                moved = 1;
  488.             }
  489.             else
  490.                print(" not found");
  491.             break;
  492.          case ALTA:case ALTC:case ALTD:
  493.          case ALTF:case ALTG:case ALTH:case ALTL:
  494.          case ALTM:case ALTP:case ALTS:case ALTB:
  495.          case ALTV:case ALTW:case ALTT:
  496.             tmpstr[0]='\0';
  497.             for (i=1;i<kw[0].opt;i++)
  498.                if (c==kw[i].key)
  499.             tmpstr[0]=kw[i].s[0];
  500.             if (tmpstr[0]=='\0')
  501.                break;
  502.             if (tmpstr[0]=='w' && !write_to)
  503.                break;
  504.             tmpstr[1]='\0';
  505.             ckey(tmpstr,kw);
  506.             psw(tmpstr[0],kw);
  507.             break;
  508.  
  509.          case '\n':     /*  **** Display ****  */
  510.             header();
  511.             break;
  512.          case '\r':
  513.             if (!Ascii)
  514.             {
  515.                if (Partial)
  516.                   dump(sec_buf,(sec_size==128)?(0):(128),sec_size,(sec_size==512)?(384):(sec_size),Radix);
  517.                else
  518.                {
  519.                   header();
  520.                   dumpf(sec_buf,sec_size,Radix);
  521.                }
  522.             }
  523.             else
  524.                 view(sec_buf,0,sec_size,NOPAUSE,Radix);
  525.             break;
  526.  
  527.          case ' ':
  528.             moved=1;
  529.             break;
  530.          case '\b':
  531.             dparams(curdir);
  532.             send('\n');
  533.             break;
  534.          case '?':
  535.             ext_commands();
  536.             break;
  537.          case '/':
  538.             commands();
  539.             break;
  540.                          /*  **** movement ****  */
  541.          case 'H':
  542.          case HOME:
  543.             if (Display)
  544.                print(" home");
  545.             rootsector();
  546.             moved=1;
  547.             break;
  548.          case 'E':
  549.          case END:
  550.             if (Display)
  551.                print(" end");
  552.             lastsector();
  553.             moved=1;
  554.             break;
  555.          case 'b':
  556.          case UP:
  557.             if (Display)
  558.                print(" back sector");
  559.             backsector();
  560.                moved=1;
  561.             break;
  562.          case 'n':
  563.          case DOWN:
  564.              if (Display)
  565.                  print(" next sector");
  566.              nextsector();
  567.              moved=1;
  568.              break;
  569.          case 'N':
  570.          case RIGHT:
  571.             if (Display)
  572.                print(" next cluster");
  573.             nextcluster();
  574.             moved=1;
  575.             break;
  576.          case 'B':
  577.          case LEFT:
  578.             if (Display)
  579.                print(" back cluster");
  580.             backcluster();
  581.             moved=1;
  582.             break;
  583.          case 'N'-'@':
  584.          case PGDN:
  585.             if (Display)
  586.                print(" next track");
  587.             nexttrack();
  588.             moved=1;
  589.             break;
  590.          case 'B'-'@':
  591.          case PGUP:
  592.             if (Display)
  593.                print(" back track");
  594.             backtrack();
  595.             moved=1;
  596.             break;
  597.          case 'h':
  598.             if (max_head==1)
  599.                break;
  600.             if (Display)
  601.                print(" next head");
  602.             nexthead();
  603.             moved=1;
  604.             break;
  605.          case 'r':
  606.          case 'R':
  607.          case CTRLR:
  608.             if (c=='R')
  609.                tempd=secs_cluster;
  610.             else
  611.                tempd=1;
  612.             if (Display)
  613.             {
  614.                print(" range ");
  615.                if (c==CTRLR)
  616.                   conout('-');
  617.                putbyte(tempd);
  618.             }
  619.             tempd *= (c==CTRLR) ? -1 : 1;
  620.             range(tempd);
  621.             break;
  622.          case '-':
  623.          case '+':
  624.          case '=':
  625.             if (Display)
  626.                print( (c=='-') ? " move back " : " move ahead ");
  627.             if (getlnumb(num_sectors,&templ) <= 0)
  628.                break;
  629.             if (templ == 0)
  630.                break;
  631.             if (c=='-')
  632.                templ *= -1;
  633.             movesector(templ);
  634.             moved = 1;
  635.             break;
  636.          case 'S':
  637.             if (Display)
  638.                print(" cluster ");
  639.             if (getnumb(num_clusters,&tempu) <= 0)
  640.                break;
  641.             if (tempu < 2)
  642.                break;
  643.             setcluster(tempu);
  644.             moved = 1;
  645.             break;
  646.          case 'S'-'@':
  647.             if (Display)
  648.                print(" sector ");
  649.             if (getlnumb(num_sectors,&templ) <= 0)
  650.                break;
  651.             setsector(templ);
  652.             moved=1;
  653.             break;
  654.          case 's':
  655.             tempt=track;
  656.             temps=sector;
  657.             temph=head;
  658.             c=set(st,&tempt,&temps,&temph);
  659.             if (c=='f')
  660.                fatsector();
  661.             else if (c=='b')
  662.                bootsector();
  663.             else if (c==0)
  664.                break;
  665.             else
  666.             {
  667.                if (tempt > max_track)
  668.                   tempt = track;
  669.                if (temps > max_sector || temps==0)
  670.                   temps = sector;
  671.                if (temph >= max_head)
  672.                   temph = head;
  673.                if (tempt==track && temps==sector && temph==head)
  674.                   break;
  675.                setphysical(tempt,temps,temph);
  676.              }
  677.              moved=1;
  678.              break;
  679.                     /*  **** Buffer stuff ****  */
  680.          case 'a':
  681.              if (byte_cnt==max_bytes)
  682.                  break;
  683.              if (Display)
  684.                  print(" append sector");
  685.              if ((byte_cnt+sec_size)>max_bytes)
  686.              {
  687.                  print(bufferfull);
  688.                  tempu=max_bytes-byte_cnt;
  689.              }
  690.              else
  691.                  tempu=sec_size;
  692.              memcpy(data_buf+byte_cnt,sec_buf,tempu);
  693.              byte_cnt+=tempu;
  694.              break;
  695.          case 'A':
  696.             if (log_sector<=data_sector)
  697.                break;
  698.             if (byte_cnt==max_bytes)
  699.                break;
  700.             if (Display)
  701.                print(" append cluster");
  702.             savesector();
  703.  
  704.             i=clustersector(log_sector);  /* goto 1st sector */
  705.             if (movesector(-i) != DISK_OK)
  706.             {
  707.                moved = 1;
  708.                restoresector();
  709.                break;
  710.             }
  711.             for (u=0;;u++)                     /* get it loop */
  712.             {
  713.                if ((byte_cnt+sec_size)>max_bytes)
  714.                   tempu=max_bytes-byte_cnt;
  715.                else
  716.                   tempu=sec_size;
  717.                memcpy(data_buf+byte_cnt,sec_buf,tempu);
  718.                if ((byte_cnt+=tempu)==max_bytes)
  719.                {
  720.                    print(bufferfull);
  721.                    break;
  722.                }
  723.                if (u == secs_cluster-1)
  724.                    break;
  725.                if (nextsector() != DISK_OK)
  726.                {
  727.                   moved = 1;
  728.                   break;
  729.                }
  730.             }
  731.             restoresector();
  732.             if (readsector() != DISK_OK)
  733.                moved = 1;
  734.             break;
  735.          case 'A'-'@':
  736.             if (byte_cnt==max_bytes) break;
  737.             if (Display)
  738.                print(" append bytes");
  739.             tempd=temps=0;  /* tempd=from, temps=number */
  740.             if (!get(ap,&tempd,&temps))
  741.                break;
  742.             if ((temps+tempd > sec_size) || temps==0)
  743.                break;
  744.             if (byte_cnt+temps > max_bytes)
  745.                break;
  746.             memcpy(data_buf+byte_cnt,sec_buf+tempd,temps);
  747.             if ((byte_cnt+=temps)==max_bytes)
  748.                print(bufferfull);
  749.             break;
  750.  
  751.          case 'u':
  752.          case 'U':
  753.             if (byte_cnt==0)
  754.                 break;
  755.             if (Display)
  756.             {
  757.                 print(" unappend ");
  758.                 print((c=='u')?"sector":"cluster");
  759.             }
  760.             tempu = (c=='u') ? sec_size : cluster_size;
  761.             if (byte_cnt < tempu)
  762.                byte_cnt = 0;
  763.             else
  764.                byte_cnt-=tempu;
  765.             break;
  766.          case 'U'-'@':
  767.             if (byte_cnt==0)
  768.                 break;
  769.             if (Display)
  770.                 print(" unappend bytes ");
  771.             if (getnumb(byte_cnt,&tempu)<=0)
  772.                 break;
  773.             if (byte_cnt < tempu)
  774.                 byte_cnt=0;
  775.             else
  776.                byte_cnt-=tempu;
  777.             break;
  778.          case 'e':
  779.          case 'E'-'@':
  780.             if (byte_cnt==0)
  781.                break;
  782.             if (Display || Verify)
  783.                print(" empty buffer");
  784.             if (c=='e' && Verify && !getver("",0))
  785.                break;
  786.             bufptr=byte_cnt=0;
  787.             break;
  788.          case 'k':
  789.             if (save_sec==NULL)
  790.                break;
  791.             if (Display)
  792.                print(" kill changes");
  793.             if (Verify && !getver("",0))
  794.                break;
  795.             memcpy(sec_buf,save_sec,sec_size);
  796.             moved=1;
  797.             break;
  798.          case '>':
  799.             if (spare_sec==NULL)
  800.                break;
  801.             if (Display || Verify)
  802.                print(" store sector");
  803.             if (Verify && !getver("",0))
  804.                break;
  805.             memcpy(spare_sec,sec_buf,sec_size);
  806.             noput=FALSE;
  807.             break;
  808.          case '<':
  809.             if (spare_sec == NULL)
  810.                break;
  811.             if (noput)
  812.             {
  813.                print(" no sector stored");
  814.                break;
  815.             }
  816.             if (Display || Verify)
  817.                print(" retrieve sector");
  818.             if (Verify && !getver("",0))
  819.                break;
  820.             memcpy(sec_buf,spare_sec,sec_size);
  821.             moved = 1;
  822.             break;
  823.          case 'd':
  824.          case 'v':
  825.             if (byte_cnt == 0)
  826.                break;
  827.             if (Display)
  828.             {
  829.                print((c == 'd') ? " dump" : " view");
  830.                print(" file buffer from ");
  831.             }
  832.             if ((tempd = getlnumb(byte_cnt,&tempu)) == ABORT)
  833.                break;
  834.             if (tempd > 0)
  835.                bufptr = tempu;
  836.             if (c == 'd')
  837.             {
  838.                send('\n');
  839.                bufptr = dump(data_buf,bufptr,byte_cnt,256,Radix);
  840.                send('\n');
  841.             }
  842.             else
  843.                bufptr = view(data_buf,bufptr,byte_cnt,PAUSE,Radix);
  844.             break;
  845.          case 'V'-'@':
  846.             if (Display)
  847.                print(" view sector");
  848.             view(sec_buf,0,sec_size,NOPAUSE,Radix);
  849.             break;
  850.          case 'c':
  851.             if (Display)
  852.                print(" change sector buffer from ");
  853.             if (change(sec_buf,sec_size,Radix))
  854.                moved = 1;
  855.             break;
  856.          case 'C':
  857.             if (!byte_cnt)
  858.                break;
  859.             if (Display)
  860.                print(" change file buffer from ");
  861.             change(data_buf,byte_cnt,Radix);
  862.             break;
  863.          case 'D'-'@':
  864.          case 'C'-'@':
  865.             if (changedir(sec_buf,sec_size))
  866.                moved = 1;
  867.             break;
  868.          case 'g':           /*** get sectors ***/
  869.          case 'G'-'@':       /* uses tempd, tempt, i */
  870.             if (byte_cnt == max_bytes)    /* full? */
  871.                break;
  872.             if (Display)                  /* display */
  873.             {
  874.                print(" get sectors ");
  875.                if (c == 'G'-'@' || Get)
  876.                    print("w/move ");
  877.             }                             /* get number */
  878.             if (getbyte(&tempu) <= 0)
  879.                break;                     /* tempd = number to get */
  880.             savesector();
  881.             if (tempu==0)                 /* 0 = get whole track from beginning */
  882.             {
  883.                tempu=max_sector;          /* count to get */
  884.                log_sector=logicalsector(track,1,head);
  885.             }
  886.             else if (tempu == 1)              /* get rest of track */
  887.                tempu = (max_sector - sector) + 1;
  888.  
  889.             if (log_sector == 0)
  890.                log_sector = num_sectors-1;
  891.             else
  892.                --log_sector;
  893.             if (Display)
  894.                conout(' ');
  895.             for (i = 1 ; i <= (int)tempu ; i++)
  896.             {
  897.                if (kbhit())
  898.                    break;
  899.                if (Display)
  900.                {
  901.                   pn(i,Radix);
  902.                   put(len(i),8);
  903.                }
  904.                if ((tempd=nextsector()) != DISK_OK)
  905.                {
  906.                   savecursor();
  907.                   if (!Display)
  908.                      conout(' ');
  909.                   printerror(Debug);
  910.                   if (!getver("continue",0))
  911.                   {
  912.                      put(3,8);
  913.                      break;
  914.                   }
  915.                   restcursor();
  916.                   clreol();
  917.                }
  918.                if ((byte_cnt+sec_size)>max_bytes)
  919.                    break;
  920.                memcpy(data_buf+byte_cnt,sec_buf,sec_size);
  921.                if ((byte_cnt+=sec_size)==max_bytes)
  922.                {
  923.                   print(bufferfull);
  924.                   break;
  925.                }
  926.             }
  927.             if (Display && tempd == DISK_OK)
  928.                clreol();
  929.             if (Get || c=='G'-'@')
  930.             {
  931.                moved = 1;
  932.                nextsector();
  933.             }
  934.             else
  935.             {
  936.                restoresector();
  937.                readsector();
  938.             }
  939.             break;
  940.          case 'l':       /*  **** Log Drive ****  */
  941.          case 'L'-'@':
  942.             if (c=='l')
  943.             {
  944.                if (Display)
  945.                    print(" disk ");
  946.                c=input();
  947.                if (!isalpha(c))
  948.                    break;
  949.                tempd=toupper(c)-'@';
  950.                if (drives[tempd]!=TRUE)
  951.                    break;
  952.                conout(toupper(c));
  953.                conout(':');
  954.                if (Verify)
  955.                {
  956.                   if (!getver("log disk",MOV_YN))
  957.                      break;
  958.                }
  959.             }
  960.             else
  961.                tempd=disk;
  962.             if (newdisk(tempd))
  963.             {
  964.                disk = tempd;
  965.                if (avail_clusters == 0)
  966.                   avail_clusters = get_avail_clusters();
  967.                dparams(curdir);
  968.                moved = 1;
  969.             }
  970.             if (error.num != -1)    /* if theres gonna be an error */
  971.             {
  972.                if (moved == 1)
  973.                {
  974.                   send('\n');       /* put it on a new line */
  975.                   send('\n');
  976.                }                    /* if its bad BOOT, reset diskio flag */
  977.                if (strcmp(error.func,"diskio")==0)/* && error.num == DISK_NREADY)*/
  978.                   diskio_error = 0;
  979.                /*printerror(Debug);*/
  980.             }
  981.             break;
  982.  
  983.             /*  **** Misc. ****  */
  984.  
  985.          case 'T':
  986.             for (i=1;i<10;i++)
  987.                if (tagged[i]!=0L)
  988.                    break;
  989.             if (i<10)
  990.             {
  991.                if (Display)
  992.                   print(" tagged sector list");
  993.                for (i=1;i<10;i++)
  994.                {
  995.                   if (!tagged[i])
  996.                      continue;
  997.                   conout(' ');
  998.                   conout(i+'0');
  999.                   conout(':');
  1000.                   pln(tagged[i],Radix);
  1001.                }
  1002.             }
  1003.             else if (Display)
  1004.                print(" no tagged sectors");
  1005.             break;
  1006.          case 't':
  1007.             if (Display)
  1008.                print(" number of this tag? ");
  1009.             if ((c=input()) < '1' || c > '9')
  1010.                break;
  1011.             conout(c);
  1012.             tagged[c-'0']=log_sector;
  1013.             break;
  1014.          case 'f':
  1015.          case '\\':
  1016.          case 'F'-'@':
  1017.             if (Display)
  1018.                print(" find ");
  1019.             tempd=find((c=='f' || c=='\\') ? (1) : (-1),1,(c=='\\') ? 1 : 0);
  1020.             if (tempd>=0)
  1021.             {
  1022.                print("\nfound at ");
  1023.                pn(tempd,Radix);
  1024.             }
  1025.             if (tempd!=ABORT)             /* user pressed ESC */
  1026.             {
  1027.                readsector();
  1028.                moved=1;
  1029.             }
  1030.             break;
  1031.          case 'F':
  1032.             if (byte_cnt==0)
  1033.                break;
  1034.             if (Display)
  1035.                print(" find ");
  1036.             if (find(0,1,0)==-1)
  1037.                print(" not found");
  1038.             break;
  1039.          case 'P':
  1040.             if (Display)
  1041.                print(" put");
  1042.             templ=log_sector;
  1043.             temps=0;               /* templ=from, temps=number */
  1044.             if (!getl(ps,&templ,&temps))
  1045.                break;
  1046.             if (templ+(long)temps > (long)num_sectors)
  1047.                break;
  1048.             if (Display)
  1049.                print(" file: ");
  1050.             else
  1051.                conout(':');
  1052.             if (getstr(tmpstr,64,_PUNCT) > 0)
  1053.             {
  1054.                if (Verify)
  1055.                {
  1056.                   if (!getver(" put file",0))
  1057.                      break;
  1058.                }
  1059.                if (exist(tmpstr))
  1060.                {
  1061.                   savecursor();
  1062.                   if (!Verify)
  1063.                      conout(' ');
  1064.                   if (!getver("exists, overwrite",0))
  1065.                      break;
  1066.                   restcursor();
  1067.                   clreol();
  1068.                }
  1069.                if (error.num == -1)
  1070.                {
  1071.                   if (Display && !Verify)
  1072.                      conout(' ');
  1073.                   else if (Display && Verify)
  1074.                   {
  1075.                      put(3,' ');
  1076.                      put(3,8);
  1077.                   }
  1078.                   putsectors(tmpstr,templ,temps);
  1079.                }
  1080.             }
  1081.             break;
  1082.          case 'P'-'@':
  1083.          case 'p':
  1084.             if (byte_cnt==0)
  1085.                break;
  1086.             if (Display)
  1087.                print(" file: ");
  1088.             getstr(tmpstr,64,_PUNCT);
  1089.             if (!tmpstr[0])
  1090.                break;
  1091.             if (Verify)
  1092.             {
  1093.                print(" put file ");
  1094.                if (Display && c=='p')
  1095.                   print("w/options");
  1096.                else if (Display)
  1097.                   print("w/o options");
  1098.                if (!getver("",0))
  1099.                   break;
  1100.             }
  1101.             if (access(tmpstr,0) == 0)
  1102.             {
  1103.                savecursor();
  1104.                if (!Verify)
  1105.                   conout(' ');
  1106.                if (!getver("exists, overwrite",0))
  1107.                   break;
  1108.                restcursor();
  1109.                clreol();
  1110.                if (unlink(tmpstr) == -1)
  1111.                   break;
  1112.             }
  1113.             if (error.num != -1)
  1114.                break;
  1115.             if (Display)
  1116.             {
  1117.                savecursor();
  1118.                if (!Verify)
  1119.                   conout(' ');
  1120.                print("putting");
  1121.                restcursor();
  1122.             }
  1123.             tempd = 1;
  1124.             putfile(tmpstr,(c=='p') ? XLATE : NOXLATE,tempd,Mask,Strip,Convert);
  1125.             break;
  1126.          case 'I'-'@':
  1127.          case 'i':
  1128.             if (byte_cnt==max_bytes)
  1129.                break;
  1130.             if (Display)
  1131.                print(" file: ");
  1132.             getstr(tmpstr,64,_PUNCT);
  1133.             if (!tmpstr[0])
  1134.                break;
  1135.             if (Verify)
  1136.             {
  1137.                print(" insert file ");
  1138.                if (Display && c=='i')
  1139.                   print("w/options");
  1140.                else if (Display)
  1141.                   print("w/o options");
  1142.                if (!getver("",0))
  1143.                   break;
  1144.             }
  1145.             if (Display)
  1146.             {
  1147.                savecursor();
  1148.                if (!Verify)
  1149.                   conout(' ');
  1150.                print("inserting");
  1151.                restcursor();
  1152.             }
  1153.             tempd=getfile(tmpstr, (c=='i') ? XLATE : NOXLATE,Mask,Strip,Convert);
  1154.             if (tempd == -2)
  1155.             {
  1156.                if (!Verify)
  1157.                   conout(' ');
  1158.                print("buffer full ");
  1159.             }
  1160.             break;
  1161.          case 'w':
  1162.             if (!write_to || !Write)
  1163.             {
  1164.                print(" write not enabled");
  1165.                break;
  1166.             }
  1167.             if (Display || Verify)
  1168.                print(" write sector");
  1169.             if (log_sector<dir_sector)
  1170.             {
  1171.                print("\a Warning! This is ");
  1172.                print((log_sector==0)?"the BOOT":"a FAT");
  1173.                print(" sector, ");
  1174.                if (!getver("write anyway",0))
  1175.                    break;
  1176.             }
  1177.             else if (Verify && !getver("",0))
  1178.                break;
  1179.             writesector();
  1180.             break;
  1181.          case 'z':
  1182.          case 'Z':
  1183.             if (Display || c=='Z')
  1184.             {
  1185.                if (Display)
  1186.                    print(" parameters");
  1187.                dkey(kw);
  1188.                if (c=='z')
  1189.                    send('\n');
  1190.                else
  1191.                    break;
  1192.             }
  1193.             if (getstr(tmpstr,MAXSTR,_PUNCT)>0)
  1194.                ckey(tmpstr,kw);
  1195.             break;
  1196.          case '0':case '1':case '2':case '3':
  1197.          case '4':case '5':case '6':case '7':
  1198.          case '8':case '9':
  1199.             c-=0x30;
  1200.             if (!tagged[c])
  1201.                break;
  1202.             if (Display || Verify)
  1203.             {
  1204.                print(" goto sector ");
  1205.                pln(tagged[c],Radix);
  1206.             }
  1207.             if (Verify && !getver("",0))
  1208.                break;
  1209.             if (log_sector!=tagged[c])
  1210.             {
  1211.                log_sector=tagged[c];
  1212.                readsector();
  1213.                moved=1;
  1214.             }
  1215.             break;
  1216.          case ',':       /* toggle radix */
  1217.             if (Radix==10)
  1218.                Radix=16;
  1219.             else
  1220.                Radix=10;
  1221.             if (Display)
  1222.             {
  1223.                print(" radix is now ");
  1224.                print((Radix==16)?"hex":"dec");
  1225.             }
  1226.             break;
  1227.          case 'D':
  1228.             if (Debug)
  1229.                debug();
  1230.             break;
  1231.          case CEND:
  1232.             if (!Files)
  1233.                break;
  1234.             tempu = sectortocluster(log_sector);
  1235.             if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
  1236.             {
  1237.                if (Display)
  1238.                   print(" end file");
  1239.                if ((tempu=endfile(clusters[tempu])) > num_clusters)
  1240.                   break;
  1241.                setcluster(tempu);
  1242.                moved=1;
  1243.             }
  1244.             break;
  1245.          case CHOME:
  1246.             if (!Files)
  1247.                break;
  1248.             tempu=sectortocluster(log_sector);
  1249.             if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
  1250.             {
  1251.                if (Display)
  1252.                   print(" home file");
  1253.                if ((tempu=homefile(clusters[tempu])) < 2)
  1254.                   break;
  1255.                setcluster(tempu);
  1256.                moved=1;
  1257.             }
  1258.             break;
  1259.          case 'm':
  1260.             if (!Files)
  1261.                break;
  1262.             tempu = sectortocluster(log_sector);
  1263.             if (clusters[tempu] > 0 && (unsigned)clusters[tempu] <= n_files)
  1264.             {
  1265.                if (Display)
  1266.                    print(" map file ");
  1267.                print(gfile(clusters[tempu]));
  1268.                send('\n');
  1269.                mapfile(clusters[tempu],Radix);
  1270.             }
  1271.             break;
  1272.          case 'M':
  1273.             if (Files)
  1274.             {
  1275.                if (Display)
  1276.                    print(" map free space");
  1277.                send('\n');
  1278.                mapdisk(Radix);
  1279.             }
  1280.             break;
  1281.          case 'j':
  1282.          case 'J':
  1283.          case CLEFT:
  1284.          case CRIGHT:
  1285.             if (!Files)
  1286.                break;
  1287.             tempu = sectortocluster(log_sector);
  1288.             temps = (c=='j' || c==CRIGHT) ? 1 : -1;
  1289.             if ((u=jumpfile(tempu,temps)) > 0)
  1290.             {
  1291.                if (u==tempu)
  1292.                   break;
  1293.                if (Display)
  1294.                {
  1295.                   print((temps==1)?" next":" back");
  1296.                   print(" file's cluster");
  1297.                }
  1298.                setcluster(u);
  1299.                moved=1;
  1300.             }
  1301.             break;
  1302.          case 'I':
  1303.             if (!Files)
  1304.                break;
  1305.             tempd=sectortocluster(log_sector);
  1306.             if (clusters[tempd] < 0 || clusters[tempd] > (int)n_files)
  1307.                break;
  1308.             if (files[clusters[tempd]].dir)
  1309.             {
  1310.                print(" can not insert directories");
  1311.                break;
  1312.             }
  1313.             sprintf(tmpstr,gfile(clusters[tempd]));
  1314.             if (Display)
  1315.             {
  1316.                print(" insert file ");
  1317.                print(tmpstr);
  1318.             }
  1319.             if (Verify)
  1320.             {
  1321.                if (!getver("",0))
  1322.                   break;
  1323.             }
  1324.             if (Display)
  1325.             {
  1326.                savecursor();
  1327.                if (!Verify)
  1328.                   conout(' ');
  1329.                print("inserting");
  1330.                restcursor();
  1331.             }
  1332.             if (getfile(tmpstr,XLATE,Mask,Strip,Convert) == -2)
  1333.             {
  1334.                if (!Verify)
  1335.                   conout(' ');
  1336.                print("buffer full ");
  1337.             }
  1338.             break;
  1339.          case 'Z'-'@':
  1340.             if (Display && !Verify)
  1341.                print(" saving");
  1342.             else if (Verify && !getver(" save",0))
  1343.                break;
  1344.             saveinit(savfile);
  1345.             break;
  1346.          case 'X'-'@':
  1347.             if (Display && !Verify)
  1348.                print(" restoring");
  1349.             else if (Verify && !getver(" restore",0))
  1350.                break;
  1351.             tempd=Home;
  1352.             Home=FALSE;
  1353.             tempt=disk;
  1354.             templ=log_sector;
  1355.             if (getinit(savfile))
  1356.             {
  1357.                if (tempt!=disk)
  1358.                {
  1359.                   if (!newdisk(disk))
  1360.                   {
  1361.                      disk=tempt;
  1362.                      log_sector=templ;
  1363.                   }
  1364.                }
  1365.                else if ((unsigned long)templ!=log_sector)
  1366.                {
  1367.                   readsector();
  1368.                   moved=1;
  1369.                }
  1370.                else if (Display)
  1371.                   send('\n');
  1372.             }
  1373.             else
  1374.             {
  1375.                disk=tempt;
  1376.                log_sector=tempu;
  1377.             }
  1378.             Home=tempd;
  1379.             break;
  1380.          case 'X':
  1381.             viewfile(savfile);
  1382.             break;
  1383.          case 'x':
  1384.             viewfile(inifile);
  1385.             break;
  1386.          case 'q':
  1387.          case '.':
  1388.          case ESC:
  1389.          case ALTX:
  1390.          case CTRLQ:
  1391.             if (Display || Verify)
  1392.                print(" exit DISKED");
  1393.             if (c!=CTRLQ && Verify && !getver("",0))
  1394.                break;
  1395.             _dos_setdrive(cdisk,&tempu);
  1396.             chdir(ccurdir);
  1397.             if (Save && c != CTRLQ)
  1398.             {
  1399.                if (Verify)
  1400.                   if (!getver(" save",1))
  1401.                break;
  1402.                if (Display)
  1403.                   print(" saving...");
  1404.                saveinit(savfile);
  1405.             }
  1406.             if (files_indexed)           /* free calls are for an IDE */
  1407.             {                            /* such as QuickC that I use */
  1408.                freep(files);
  1409.                freep(clusters);
  1410.             }
  1411.             if (spare_sec)
  1412.                freep(spare_sec);
  1413.             if (save_sec)
  1414.                freep(save_sec);
  1415.             freep(sec_buf);
  1416.             freep(data_buf);
  1417.             return(0);
  1418.             break;
  1419.          default:
  1420.              break;
  1421.         }
  1422.     }
  1423. }
  1424.